import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import static java.lang.Thread.sleep;

class MyBlockQueue {
    private int[] elems = null;
    private volatile int head = 0;//头位置
    private volatile int tail = 0;//插入位置
    private volatile int size = 0;//数组个数
    public MyBlockQueue(int capacity) {
        elems = new int[capacity];
    }
    //插入
    void put(int  elem) throws InterruptedException {
        synchronized(this) {
            if(size >= elems.length) {
               wait();
            }
            elems[tail] = elem;
            tail++;
            if(tail >= elems.length) {
                tail = 0;
            }
            size++;
            notify();
        }
    }
    //取出
    int take() throws InterruptedException {
        synchronized(this) {
            if(size == 0) {
                wait();
            }
            int ret = elems[head];
            head++;
            if(head >= elems.length) {
                head = 0;
            }
            size--;
            notify();
            return ret;
        }
    }
}
public class Test {
    /**
     * 认识线程
     *      多线程案例
     */
    /**
     * 线程池
     *      线程池最⼤的好处就是减少每次启动、销毁线程的损耗
     */
    public static void main2(String[] args) {
        /**
         * Executors 创建线程池的⼏种⽅式
         *      newFixedThreadPool: 创建固定线程数的线程池
         *      newCachedThreadPool: 创建线程数⽬动态增⻓的线程池
         *      newSingleThreadExecutor: 创建只包含单个线程的线程池
         *      newScheduledThreadPool: 设定 延迟时间后执⾏命令，或者定期执⾏命令. 是进阶版的 Timer.
         * Executors 本质上是 ThreadPoolExecutor 类的封装
         *
         *
         * 参数
         *      corePoolSize: 正式员⼯的数量. (正式员⼯, ⼀旦录⽤, 永不辞退)
         *      maximumPoolSize: 正式员⼯ + 临时⼯的数⽬. (临时⼯: ⼀段时间不⼲活, 就被辞退)
         *      keepAliveTime: 临时⼯允许的空闲时间
         *      unit: keepaliveTime 的时间单位, 是秒, 分钟, 还是其他值
         *      workQueue: 传递任务的阻塞队列
         *      threadFactory: 创建线程的⼯⼚, 参与具体的创建线程⼯作. 通过不同线程⼯⼚创建出的线程相当于
         * 对⼀些属性进⾏了不同的初始化设置.
         *      RejectedExecutionHandler: 拒绝策略, 如果任务量超出公司的负荷了接下来怎么处理
         *          AbortPolicy(): 超过负荷, 直接抛出异常
         *          CallerRunsPolicy(): 调⽤者负责处理多出来的任务.
         *          DiscardOldestPolicy(): 丢弃队列中最⽼的任务.
         *          DiscardPolicy(): 丢弃新来的任务
         */
    }
    public static void main1(String[] args) throws InterruptedException {
        MyBlockQueue queue = new MyBlockQueue(1000);
        //消费者
        Thread t1 = new Thread(() -> {
            try {
                while (true) {
                    int value = queue.take();
                    System.out.println("t1消费: " + value);
                    sleep(1000);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        //生产者
        Thread t2 = new Thread(() -> {
            try {
                int count = 1;
                while (true) {
                    queue.put(count);
                    System.out.println("t2生产: " + count);
                    count++;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}
